package jmine.tec.script.persistent.repository;

import static jmine.tec.script.persistent.domain.enumx.BaseScriptPurposeIdentifier.API;
import static jmine.tec.script.persistent.domain.enumx.BaseScriptPurposeIdentifier.INIT;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.Map;

import jmine.tec.script.persistent.domain.Script;
import jmine.tec.script.persistent.domain.ScriptDependency;
import jmine.tec.script.persistent.domain.ScriptLanguage;
import jmine.tec.script.persistent.domain.ScriptPurpose;
import jmine.tec.script.persistent.driver.ScriptBean;
import bancosys.tec.datadigester.DefaultDigesterFile;
import bancosys.tec.datadigester.DigesterDriver;
import bancosys.tec.datadigester.input.ResetableInputStreamFactory;

/**
 * Loader de scripts que utilizam a entidade base de scripts persistíveis.
 * 
 * @author lundberg
 */
public class BaseScriptLoader implements ScriptLoader {

    private final String type;

    private final DigesterDriver<ScriptBean> driver;

    /**
     * Construtor
     * 
     * @param type type
     * @param driver driver
     */
    public BaseScriptLoader(String type, DigesterDriver<ScriptBean> driver) {
        this.type = type;
        this.driver = driver;
    }

    /**
     * {@inheritDoc}
     */
    public Script load(TransientScriptRepository repository, String path) {
        URL url = this.getClass().getClassLoader().getResource(path);
        if (url == null) {
            throw new NullPointerException("Arquivo não encontrado no classpath: " + path);
        }
        InputStream input;
        try {
            input = url.openStream();
        } catch (IOException e) {
            throw new RuntimeException("Erro de I/O lendo arquivo " + path, e);
        }

        DefaultDigesterFile file = new DefaultDigesterFile(path, ResetableInputStreamFactory.createResetableInputStream(input));
        ScriptBean bean = this.driver.parse(file, Collections.<String, String> emptyMap());

        ScriptPurpose purpose = repository.findPurpose(bean.getFinalidade());
        ScriptLanguage language = repository.findLanguage(bean.getLanguageIdentifier());

        Script script = new Script();
        script.setId(bean.getDatabaseId() == null ? null : Long.parseLong(bean.getDatabaseId()));
        script.setVersion(0L);
        script.setDescricao(bean.getDescricao());
        script.setBody(bean.getBody());
        script.setPurpose(purpose);

        if (purpose.isIdentifiedBy(API) || purpose.isIdentifiedBy(INIT)) {
            script.setMnemonico(String.format("%s_%s", bean.getMnemonico(), language.getAbreviacao()));
        } else {
            script.setMnemonico(bean.getMnemonico());
        }
        script.setLanguage(language);

        for (String api : bean.getApis()) {
            script.getApis().add(repository.loadScript(api, language));
        }
        for (Map.Entry<String, String> e : bean.getDependencies().entrySet()) {
            ScriptDependency dependency = new ScriptDependency();
            dependency.setVariable(e.getKey());
            dependency.setBean(e.getValue());
            script.getDependencies().add(dependency);
        }
        return script;
    }

    /**
     * {@inheritDoc}
     */
    public String type() {
        return this.type;
    }
}
